package de.zainodis.commons.utils;

import org.xmlpull.v1.XmlPullParser;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import de.zainodis.commons.LogCat;

public class ResourceUtils {

   private static final String TAG = "ResourceUtils";

   /** The identifier to use when referencing string references */
   public static final String STRING_RESOURCE_IDENTIFIER = "@string/";

   /** The resource type for strings (used via @string/...) */
   public final static String STRING_RESOURCE_TYPE = "string";

   /** The resource type for xml */
   public final static String XML_RESOURCE_TYPE = "xml";

   /** The resource type for drawables */
   public final static String DRAWABLE_RESOURCE_TYPE = "drawable";

   /** Zero represents an invalid resource ID */
   public final static int INVALID_RESOURCE_ID = 0;

   /**
    * A regular expression to extract a string resource name from a string
    * resource declaration. An example for a string resource declaration would
    * be "@string/hello"). The extracted resource name would be "hello".
    */
   public static final String STRING_RESOURCE_EXTRACTION_PATTERN = STRING_RESOURCE_IDENTIFIER
	    + "(.*)";

   public static Drawable getDrawableResource(Context context, String name) {
	 Resources res = context.getResources();
	 // Attempt to turn the given drawable resource name into a res id
	 int resId = res.getIdentifier(name, DRAWABLE_RESOURCE_TYPE, context.getPackageName());
	 if (resId != INVALID_RESOURCE_ID) {
	    // We've found a valid resource ID
	    return res.getDrawable(resId);
	 } else {
	    LogCat.w(TAG, "No valid resource found matching drawable resource name " + name);
	    return null;
	 }
   }

   /**
    * Attempts to extract a string resource from the given {@link Resources}s
    * that matches the given string resource name. A valid string resource would
    * be for instance: hello. The String resource name "hello" must exist in
    * your application as a String resource.
    * 
    * @param res
    *           the Resources in which to search.
    * @param stringResourceName
    *           the name of the string resource.
    * @return the String value of the given string resource name; or null if no
    *         match was found.
    */
   public static String getString(Context context, String stringResourceName) {
	 Resources res = context.getResources();
	 String packageName = context.getPackageName();
	 // Attempt to turn the given string resource name into a res id
	 int resId = res.getIdentifier(stringResourceName, STRING_RESOURCE_TYPE, packageName);
	 if (resId != INVALID_RESOURCE_ID) {
	    // We've found a valid resource ID
	    try {
		  return res.getString(resId);
	    } catch (Resources.NotFoundException e) {
		  // Is being logged later
	    }
	 }
	 LogCat.w(TAG, "No valid resource found matching string resource name " + stringResourceName);
	 return null;
   }

   /**
    * Attempts to obtain the matching Xml resource for the given resource name,
    * within the given context.
    * 
    * @param context
    *           the context in which the xml resource resides.
    * @param name
    *           the name of the resource (file name).
    * @return the Xml resource as a {@link XmlPullParser}; or null if no
    *         matching resource was found.
    */
   public static XmlPullParser getXmlResource(Context context, String name) {
	 Resources res = context.getResources();
	 // Attempt to turn the given xml resource name into a res id
	 int resId = res.getIdentifier(name, XML_RESOURCE_TYPE, context.getPackageName());
	 if (resId != INVALID_RESOURCE_ID) {
	    // We've found a valid resource ID
	    return res.getXml(resId);
	 } else {
	    LogCat.w(TAG, "No valid resource found matching xml resource name " + name);
	    return null;
	 }
   }

   /**
    * Checks if the given string value references a string resource.
    * 
    * @param value
    *           the string value to check.
    * @return true if the given value contains is a string-resource-reference;
    *         false otherwise.
    */
   public static boolean isAStringResource(String value) {
	 if (value != null) {
	    return (value.startsWith(STRING_RESOURCE_IDENTIFIER));
	 }
	 return false;
   }

   /**
    * The given value must be of the format "@string/resourceName". The return
    * value in this case would be "resourceName".
    * 
    * @param value
    *           the value from which to extract the string resource name.
    * @return the string resource name, if a validly formatted string has been
    *         provided; or null if not.
    */
   public static String extractStringResourceName(String value) {
	 if (isAStringResource(value)) {
	    String[] matches = RegexUtils.parse(STRING_RESOURCE_EXTRACTION_PATTERN, value);
	    // We're only interested in the last group match, since the first
	    // group would be the entire passed value (including the @string/
	    // prefix, which we want to remove)
	    return matches[matches.length - 1];
	 }
	 return null;
   }

}
